<?php
/**
 * ZFDebug Zend Additions
 *
 * @category   ZFDebug
 * @package    Anderles_Controller
 * @subpackage Plugins
 * @copyright  Copyright (c) 2008-2009 ZF Debug Bar Team (http://code.google.com/p/ZFDebug)
 * @license    http://code.google.com/p/ZFDebug/wiki/License     New BSD License
 * @version    $Id: Debug.php 83 2009-05-21 13:36:05Z gugakfugl $
 */

/**
 * @see Zend_Controller_Exception
 */
require_once 'Zend/Controller/Exception.php';

/**
 * @see Zend_Version
 */
require_once 'Zend/Version.php';

/**
 * @see Anderles_Controller_Plugin_Debug_Plugin_Text
 */
require_once 'Anderles/Controller/Plugin/Debug/Plugin/Text.php';

/**
 * @category   ZFDebug
 * @package    Anderles_Controller
 * @subpackage Plugins
 * @copyright  Copyright (c) 2008-2009 ZF Debug Bar Team (http://code.google.com/p/ZFDebug)
 * @license    http://code.google.com/p/ZFDebug/wiki/License     New BSD License
 */
class Anderles_Controller_Plugin_Debug extends Zend_Controller_Plugin_Abstract
{
    /**
     * Contains registered plugins
     *
     * @var array
     */
    protected $_plugins = array();

    /**
     * Contains options to change Debug Bar behavior
     */
    protected $_options = array(
        'plugins'           => array(
            'Variables' => null,
            'Time' => null,
            'Memory' => null),
        'z-index'           => 255,
        'jquery_path'       => 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js',
        'image_path'        => null
    );
    
    /**
     * Standard plugins
     *
     * @var array
     */
    public static $standardPlugins = array('Cache', 'Html', 'Database', 'Exception', 'File', 'Memory', 'Registry', 'Time', 'Variables');

    /**
     * Debug Bar Version Number
     * for internal use only
     *
     * @var string
     */
    protected $_version = '1.5';

    /**
     * Creates a new instance of the Debug Bar
     *
     * @param array|Zend_Config $options
     * @throws Zend_Controller_Exception
     * @return void
     */
    public function __construct($options = null)
    {
        if (isset($options)) {
            if ($options instanceof Zend_Config) {
                $options = $options->toArray();
            }

            /*
             * Verify that adapter parameters are in an array.
             */
            if (!is_array($options)) {
                throw new Zend_Exception('Debug parameters must be in an array or a Zend_Config object');
            }

            $this->setOptions($options);
        }
        
        /**
         * Creating ZF Version Tab always shown
         */
        $version = new Anderles_Controller_Plugin_Debug_Plugin_Text();
        $version->setPanel($this->_getVersionPanel())
                ->setTab($this->_getVersionTab())
                ->setIdentifier('copyright');
        $this->registerPlugin($version);

        /**
         * Loading aready defined plugins
         */
        $this->_loadPlugins();
    }
    
    /**
     * Sets options of the Debug Bar
     *
     * @param array $options
     * @return Anderles_Controller_Plugin_Debug
     */
    public function setOptions(array $options = array())
    {
        if (isset($options['jquery_path'])) {
            $this->_options['jquery_path'] = $options['jquery_path'];
        }

        if (isset($options['z-index'])) {
            $this->_options['z-index'] = $options['z-index'];
        }

        if (isset($options['image_path'])) {
            $this->_options['image_path'] = $options['image_path'];
        }
        
        if (isset($options['plugins'])) {
        	$this->_options['plugins'] = $options['plugins'];
        }
        return $this;
    }

    /**
     * Register a new plugin in the Debug Bar
     *
     * @param Anderles_Controller_Plugin_Debug_Plugin_Interface
     * @return Anderles_Controller_Plugin_Debug
     */
    public function registerPlugin(Anderles_Controller_Plugin_Debug_Plugin_Interface $plugin)
    {
        $this->_plugins[$plugin->getIdentifier()] = $plugin;
        return $this;
    }

    /**
     * Unregister a plugin in the Debug Bar
     *
     * @param string $plugin
     * @return Anderles_Controller_Plugin_Debug
     */
    public function unregisterPlugin($plugin)
    {
        if (false !== strpos($plugin, '_')) {
            foreach ($this->_plugins as $key => $_plugin) {
                if ($plugin == get_class($_plugin)) {
                    unset($this->_plugins[$key]);
                }
            }
        } else {
            $plugin = strtolower($plugin);
            if (isset($this->_plugins[$plugin])) {
                unset($this->_plugins[$plugin]);
            }
        }
        return $this;
    }
    
    /**
     * Get a registered plugin in the Debug Bar
     *
     * @param string $identifier
     * @return Anderles_Controller_Plugin_Debug_Plugin_Interface
     */
    public function getPlugin($identifier)
    {
        $identifier = strtolower($identifier);
        if (isset($this->_plugins[$identifier])) {
            return $this->_plugins[$identifier];
        }
        return false;
    }
    
    /**
     * Defined by Zend_Controller_Plugin_Abstract
     */
    public function dispatchLoopShutdown()
    {
        $html = '';

        if ($this->getRequest()->isXmlHttpRequest())
            return;

        /**
         * Creating menu tab for all registered plugins
         */
        foreach ($this->_plugins as $plugin)
        {
            $panel = $plugin->getPanel();
            if ($panel == '') {
                continue;
            }

            /* @var $plugin Anderles_Controller_Plugin_Debug_Plugin_Interface */
            $html .= '<div id="Anderles_' . $plugin->getIdentifier()
                  . '" class="Anderles_panel">' . $panel . '</div>';
        }

        $html .= '<div id="Anderles_info">';

        /**
         * Creating panel content for all registered plugins
         */
        foreach ($this->_plugins as $plugin)
        {
            $tab = $plugin->getTab();
            if ($tab == '') {
                continue;
            }

            /* @var $plugin Anderles_Controller_Plugin_Debug_Plugin_Interface */
            $html .= '<span class="Anderles_span clickable" onclick="ZFDebugPanel(\'Anderles_' . $plugin->getIdentifier() . '\');">';
            $html .= '<img src="' . $this->_icon($plugin->getIdentifier()) . '" style="vertical-align:middle" alt="' . $plugin->getIdentifier() . '" title="' . $plugin->getIdentifier() . '" /> ';
            $html .= $tab . '</span>';
        }

        $html .= '<span class="Anderles_span Anderles_last clickable" id="Anderles_toggler" onclick="ZFDebugSlideBar()">&#171;</span>';

        $html .= '</div>';
        $this->_output($html);
    }

    ### INTERNAL METHODS BELOW ###

    /**
     * Load plugins set in config option
     *
     * @return void;
     */
    protected function _loadPlugins()
    {
    	foreach($this->_options['plugins'] as $plugin => $options) {
    	    if (is_numeric($plugin)) {
    	        # Plugin passed as array value instead of key
    	        $plugin = $options;
    	        $options = array();
    	    }
    	    $plugin = (string)$plugin;
    	    if (in_array($plugin, Anderles_Controller_Plugin_Debug::$standardPlugins)) {
    	        // standard plugin
                $pluginClass = 'Anderles_Controller_Plugin_Debug_Plugin_' . $plugin;
    	    } else {
    	        // we use a custom plugin
                if (!preg_match('~^[\w]+$~D', $plugin)) {
                    throw new Zend_Exception("ZFDebug: Invalid plugin name [$plugin]");
                }
                $pluginClass = $plugin;
            }

            require_once str_replace('_', DIRECTORY_SEPARATOR, $pluginClass) . '.php';
            $object = new $pluginClass($options);
    		$this->registerPlugin($object);
    	}
    }

    /**
     * Return version tab
     *
     * @return string
     */
    protected function _getVersionTab()
    {
        return ' ' . Zend_Version::VERSION . '/'.phpversion();
    }

    /**
     * Returns version panel
     *
     * @return string
     */
    protected function _getVersionPanel()
    {
        $panel = '<h4>ZFDebug v'.$this->_version.'</h4>' .
                 '<p>©2008-2009 <a href="http://jokke.dk">Joakim Nygård</a> & <a href="http://www.bangal.de">Andreas Pankratz</a></p>' .
                 '<p>The project is hosted at <a href="http://code.google.com/p/ZFDebug/">http://ZFDebug.googlecode.com</a> and released under the BSD License<br />' .
                 'Includes images from the <a href="http://www.famfamfam.com/lab/icons/silk/">Silk Icon set</a> by Mark James</p>';
        // $panel .= '<h4>Zend Framework '.Zend_Version::VERSION.' / PHP '.phpversion().' with extensions:</h4>';
        // $extensions = get_loaded_extensions();
        // natcasesort($extensions);
        // $panel .= implode('<br>', $extensions);
        return $panel;
    }

    /**
     * Returns path to the specific icon
     *
     * @return string
     */
    protected function _icon($kind)
    {
        switch ($kind) {
            case 'database':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/database.png';
                break;
            case 'time':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/time.png';
            case 'memory':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/memory.png';
                break;
            case 'copyright':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/copyright.gif';
                break;
            case 'variables':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/variables.png';
                break;
            case 'exception':
                if (null === $this->_options['image_path'])
    				return '';

                return $this->_options['image_path'] . '/exception.png';
                 break;
            case 'error':
                if (null === $this->_options['image_path'])
    			    return '';

                return $this->_options['image_path'] . '/error.png';
                break;
            case 'cache':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/cache.png';
                break;
            case 'text':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/text.png';
                break;
            case 'file':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/file.png';
                break;
            case 'auth':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/auth.png';
                break;
            case 'registry':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/registry.png';
                break;
            case 'html':
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/html.png';
                break;
            default:
                if (null === $this->_options['image_path'])
                    return '';

                return $this->_options['image_path'] . '/unknown.png';
                break;
        }
    }

    /**
     * Returns html header for the Debug Bar
     *
     * @return string
     */
    protected function _headerOutput() {
        $collapsed = isset($_COOKIE['ZFDebugCollapsed']) ? $_COOKIE['ZFDebugCollapsed'] : 0;

        return ('
            <style type="text/css" media="screen">
                #Anderles_debug { font: 11px/1.4em Lucida Grande, Lucida Sans Unicode, sans-serif; position:fixed; bottom:5px; left:5px; color:#000; z-index: ' . $this->_options['z-index'] . ';}
                #Anderles_debug ol {margin:10px 0px; padding:0 25px}
                #Anderles_debug li {margin:0 0 10px 0;}
                #Anderles_debug .clickable {cursor:pointer}
                #Anderles_toggler { font-weight:bold; background:#BFBFBF; }
                .Anderles_span { border: 1px solid #999; border-right:0px; background:#DFDFDF; padding: 5px 5px; }
                .Anderles_last { border: 1px solid #999; }
                .Anderles_panel { text-align:left; position:absolute;bottom:21px;width:600px; max-height:400px; overflow:auto; display:none; background:#E8E8E8; padding:5px; border: 1px solid #999; }
                .Anderles_panel .pre {font: 11px/1.4em Monaco, Lucida Console, monospace; margin:0 0 0 22px}
                #Anderles_exception { border:1px solid #CD0A0A;display: block; }
            </style>
            <script type="text/javascript" charset="utf-8">
                if (typeof jQuery == "undefined") {
                    var scriptObj = document.createElement("script");
                    scriptObj.src = "'.$this->_options['jquery_path'].'";
                    scriptObj.type = "text/javascript";
                    var head=document.getElementsByTagName("head")[0];
                    head.insertBefore(scriptObj,head.firstChild);
                }

                var ZFDebugLoad = window.onload;
                window.onload = function(){
                    if (ZFDebugLoad) {
                        ZFDebugLoad();
                    }
                    jQuery.noConflict();
                    ZFDebugCollapsed();
                };
                
                function ZFDebugCollapsed() {
                    if ('.$collapsed.' == 1) {
                        ZFDebugPanel();
                        jQuery("#Anderles_toggler").html("&#187;");
                        return jQuery("#Anderles_debug").css("left", "-"+parseInt(jQuery("#Anderles_debug").outerWidth()-jQuery("#Anderles_toggler").outerWidth()+1)+"px");
                    }
                }
                
                function ZFDebugPanel(name) {
                    jQuery(".Anderles_panel").each(function(i){
                        if(jQuery(this).css("display") == "block") {
                            jQuery(this).slideUp();
                        } else {
                            if (jQuery(this).attr("id") == name)
                                jQuery(this).slideDown();
                            else
                                jQuery(this).slideUp();
                        }
                    });
                }

                function ZFDebugSlideBar() {
                    if (jQuery("#Anderles_debug").position().left > 0) {
                        document.cookie = "ZFDebugCollapsed=1;expires=;path=/";
                        ZFDebugPanel();
                        jQuery("#Anderles_toggler").html("&#187;");
                        return jQuery("#Anderles_debug").animate({left:"-"+parseInt(jQuery("#Anderles_debug").outerWidth()-jQuery("#Anderles_toggler").outerWidth()+1)+"px"}, "normal", "swing");
                    } else {
                        document.cookie = "ZFDebugCollapsed=0;expires=;path=/";
                        jQuery("#Anderles_toggler").html("&#171;");
                        return jQuery("#Anderles_debug").animate({left:"5px"}, "normal", "swing");
                    }
                }

                function ZFDebugToggleElement(name, whenHidden, whenVisible){
                    if(jQuery(name).css("display")=="none"){
                        jQuery(whenVisible).show();
                        jQuery(whenHidden).hide();
                    } else {
                        jQuery(whenVisible).hide();
                        jQuery(whenHidden).show();
                    }
                    jQuery(name).slideToggle();
                }
            </script>');
    }

    /**
     * Appends Debug Bar html output to the original page
     *
     * @param string $html
     * @return void
     */
    protected function _output($html)
    {
        $response = $this->getResponse();
        $response->setBody(preg_replace('/(<head.*>)/i', '$1' . $this->_headerOutput(), $response->getBody()));
        $response->setBody(str_ireplace('</body>', '<div id="Anderles_debug">'.$html.'</div></body>', $response->getBody()));
    }
}